//package com.naiterui.ehp.bp.support.aspect;
//
//import com.google.common.collect.ImmutableList;
//import com.google.common.collect.Lists;
//import com.naiterui.ehp.bp.support.utils.web.RequestHolder;
//import java.lang.reflect.Method;
//import java.util.List;
//import javax.servlet.http.HttpServletRequest;
//import lombok.AllArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.springframework.stereotype.Component;
//
//@Slf4j
//@Aspect
//@Component
//@AllArgsConstructor
//public class LimitAspect {
//
//    private final RedisTemplate<Object, Object> redisTemplate;
//
//    public LimitAspect(RedisTemplate<Object, Object> redisTemplate) {
//        this.redisTemplate = redisTemplate;
//    }
//
//    @Pointcut("@annotation(com.pepsi.common.annotation.Limit)")
//    public void pointcut() {
//    }
//
//    @Around("pointcut()")
//    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//        HttpServletRequest request = RequestHolder.getHttpServletRequest();
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        Method signatureMethod = signature.getMethod();
//        Limit limit = signatureMethod.getAnnotation(Limit.class);
//        LimitType limitType = limit.limitType();
//        String key = limit.key();
//        if (StringUtils.isEmpty(key)) {
//            if (limitType == LimitType.IP) {
//                key = IpUtil.getIp(request);
//            } else {
//                key = signatureMethod.getName();
//            }
//        }
//
//        List<String> elements = Lists.newArrayList(limit.prefix(), "_", key, "_", request.getRequestURI().replaceAll("/", "_"));
//        ImmutableList<Object> keys = ImmutableList.of(String.join("-", elements));
//        String luaScript = this.buildLuaScript();
//        RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class);
//        Number count = this.redisTemplate.execute(redisScript, keys, limit.count(), limit.period());
//        if (null != count && count.intValue() <= limit.count()) {
//            log.info("第{}次访问key为 {}，描述为 [{}] 的接口", count, keys, limit.name());
//            return joinPoint.proceed();
//        }
//        throw new BadRequestException("访问次数受限制");
//    }
//
//    /**
//     * 限流脚本
//     */
//    private String buildLuaScript() {
//        return "local c" +
//                "\nc = redis.call('get',KEYS[1])" +
//                "\nif c and tonumber(c) > tonumber(ARGV[1]) then" +
//                "\nreturn c;" +
//                "\nend" +
//                "\nc = redis.call('incr',KEYS[1])" +
//                "\nif tonumber(c) == 1 then" +
//                "\nredis.call('expire',KEYS[1],ARGV[2])" +
//                "\nend" +
//                "\nreturn c;";
//    }
//}
